#include "logupload.h"

uint8_t LogStart[] = {  0xa5, 0xff, 0x5a, 0xff, // header
                        0x0a, 0x00, 0x00, 0x00, // type
                        0x10, 0x00, 0x00, 0x00, // subtype
                        0x00, 0x00, 0x00, 0x00, // subtype1
                        0x01, 0x00, 0x00, 0x00, // length
                        0xE5,                   // checksum
                        0x01,                   // data
                        0x5a, 0xff, 0xa5, 0xff, // tail
};

uint8_t LogRsp[] =   {  0xa5, 0xff, 0x5a, 0xff, // header
                        0x0b, 0x00, 0x00, 0x00, // type
                        0x06, 0x00, 0x00, 0x00, // subtype
                        0x00, 0x00, 0x00, 0x00, // subtype1
                        0x02, 0x00, 0x00, 0x00, // length
                        0xed,                   // checksum
                        0x01,                   // ack 
                        0x00,                   // error code
                        0x5a, 0xff, 0xa5, 0xff, // tail
};

uint8_t LogNext[] =  {  0xa5, 0xff, 0x5a, 0xff, // header
                        0x0f, 0x00, 0x00, 0x00, // type
                        0x02, 0x00, 0x00, 0x00, // subtype
                        0x00, 0x00, 0x00, 0x00, // subtype1
                        0x01, 0x00, 0x00, 0x00, // length
                        0xEE,                   // checksum
                        0x00,                   // data
                        0x5a, 0xff, 0xa5, 0xff, // tail
};

#pragma pack(push, 1)
struct upload_message
{
    uint32_t message_type;
    uint32_t sub_type;
    uint32_t sub_type1;
    uint32_t length;
    uint8_t  checksum;
    uint8_t  request_type;
    uint32_t data_len;
    char     md5[32];
    char     name[128];
};
#pragma pack(pop)

#pragma pack(push, 1)
struct upload_log_message
{
    uint32_t message_type;
    uint32_t sub_type;
    uint32_t sub_type1;
    uint32_t length;
    uint8_t  checksum;

    uint32_t  len;
    uint16_t  status_flag;
};
#pragma pack(pop)

#pragma pack(push, 1)
struct upload_end_message
{
    uint32_t header;
    uint32_t message_type;
    uint32_t sub_type;
    uint32_t sub_type1;
    uint32_t length;
    uint8_t  checksum;

    char     name[128];
    uint8_t  status;
    uint8_t  flag;
    uint32_t tail;
};
#pragma pack(pop)

std::unique_ptr<LogUpload> LogUpload::LogUploadInstance = nullptr;

std::unique_ptr<LogUpload>& LogUpload::getInstance()
{
    static std::once_flag flag;
    std::call_once(flag, []() {
        LogUploadInstance = std::make_unique<LogUpload>();
    });
    return LogUploadInstance;
}

LogUpload::LogUpload() {
    qDebug() << "LogUpload Start";

    server10001 = new QTcpServer(this);
    if (!server10001->listen(QHostAddress::Any, 10001)) {
        qDebug() << "监听10001端口失败:" << server10001->errorString();
        return;
    }
    connect(server10001, &QTcpServer::newConnection, this, &LogUpload::handleConnection10001);

    server10002 = new QTcpServer(this);
    if (!server10002->listen(QHostAddress::Any, 10002)) {
        qDebug() << "监听10002端口失败:" << server10002->errorString();
        return;
    }
    connect(server10002, &QTcpServer::newConnection, this, &LogUpload::handleConnection10002);
}

LogUpload::~LogUpload() {
    if (server10001) {
        server10001->close();
        delete server10001;
    }
    if (server10002) {
        server10002->close();
        delete server10002;
    }
}

void LogUpload::LogRequest() {
    if((!LogRequestFlag) && (socket10001))
    {
        QFile file("log.zip");
        if (file.exists()) {
            if (file.remove()) {
                qDebug() << "Successfully deleted log.zip";
            } else {
                qDebug() << "Failed to delete log.zip: " << file.errorString();
            }
        } else {
            qDebug() << "log.zip does not exist.";
        }

        QByteArray data(reinterpret_cast<const char*>(LogStart), sizeof(LogStart));
        qint64 bytesWritten = socket10001->write(data);
        if (bytesWritten == -1) {
            qDebug() << "Failed to send message to client";
        } else {
            qDebug() << "Successfully sent message to client, bytes written: " << bytesWritten;
        }
        LogRequestFlag = true; // 日志正在传输的标志位
    }
}

void LogUpload::readDataPort10001() {
    QByteArray data = socket10001->readAll();
    QString hexData = data.toHex(' '); // 以空格分隔每个字节的十六进制表示
    qDebug() << "Received data from client (hex) size :  " << data.size();
    qDebug() << hexData;

    // 检查数据长度是否足够
    if (data.size() < 8 + sizeof(upload_message)) {
        qDebug() << "PORT10001 Received data is too short.";
        return;
    }

    // 检查前 4 个字节
    const unsigned char expectedHeader[4] = {0xa5, 0xff, 0x5a, 0xff};
    for (int i = 0; i < 4; ++i) {
        if (static_cast<unsigned char>(data[i]) != expectedHeader[i]) {
            qDebug() << "Header does not match.";
            return;
        }
    }

    // 检查后 4 个字节
    const unsigned char expectedFooter[4] = {0x5a, 0xff, 0xa5, 0xff};
    for (int i = 0; i < 4; ++i) {
        if (static_cast<unsigned char>(data[data.size() - 4 + i]) != expectedFooter[i]) {
            qDebug() << "Footer does not match.";
            return;
        }
    }

    // 解析结构体
    // const upload_message* msg = reinterpret_cast<const upload_message*>(data.constData() + 4);
    // qDebug() << "message_type : " << QString("%1").arg(msg->message_type, 8, 16, QChar('0'));
    // qDebug() << "sub_type : " << QString("%1").arg(msg->sub_type, 8, 16, QChar('0'));
    // qDebug() << "sub_type1 : " << QString("%1").arg(msg->sub_type1, 8, 16, QChar('0'));
    // qDebug() << "length : " << msg->length;
    // qDebug() << "checksum : " << QString("%1").arg(msg->checksum, 8, 16, QChar('0'));
    // qDebug() << "request_type : " << QString("%1").arg(msg->request_type, 8, 16, QChar('0'));
    // qDebug() << "data_len : " << msg->data_len;

    // QString md5Str = QString::fromLatin1(msg->md5, 32);
    // qDebug() << "md5: " << md5Str;

    // QString nameStr(msg->name);
    // qDebug() << "name: " << nameStr;

    QByteArray data1(reinterpret_cast<const char*>(LogRsp), sizeof(LogRsp));
    // 向客户端发送消息
    qint64 bytesWritten = socket10001->write(data1);
    if (bytesWritten == -1) {
        qDebug() << "Failed to send Log Response message to client";
    } else {
        qDebug() << "Successfully sent Log Response message to client, bytes written: " << bytesWritten;
    }
}

void LogUpload::readDataPort10002() {
    buffer.append(socket10002->readAll());

    const unsigned char expectedHeader[4] = {0xa5, 0xff, 0x5a, 0xff};
    const unsigned char expectedFooter[4] = {0x5a, 0xff, 0xa5, 0xff};

    while (buffer.size() >= 8) { // 至少要有帧头和帧尾的长度
        int headerIndex = buffer.indexOf(QByteArray::fromRawData(reinterpret_cast<const char*>(expectedHeader), 4));
        if (headerIndex == -1) {
            // 没有找到帧头，清空缓冲区
            buffer.clear();
            break;
        }
        if (headerIndex > 0) {
            // 移除帧头之前的数据
            buffer.remove(0, headerIndex);
        }

        int footerIndex = buffer.indexOf(QByteArray::fromRawData(reinterpret_cast<const char*>(expectedFooter), 4), 4);
        if (footerIndex == -1) {
            // 没有找到帧尾，等待更多数据
            break;
        }

        int frameLength = footerIndex + 4;
        QByteArray frame = buffer.left(frameLength);
        buffer.remove(0, frameLength);

        // 检查帧头和帧尾
        bool headerMatched = true;
        bool footerMatched = true;
        for (int i = 0; i < 4; ++i) {
            if (static_cast<unsigned char>(frame[i]) != expectedHeader[i]) {
                headerMatched = false;
                break;
            }
        }
        for (int i = 0; i < 4; ++i) {
            if (static_cast<unsigned char>(frame[frame.size() - 4 + i]) != expectedFooter[i]) {
                footerMatched = false;
                break;
            }
        }

        if (headerMatched && footerMatched) {
            qDebug() << "PORT10002 recv data size : "<< frame.size();

            // 解析结构体
            const upload_log_message* msg = reinterpret_cast<const upload_log_message*>(frame.constData() + 4);
            // qDebug() << "message_type : " << QString("%1").arg(msg->message_type, 8, 16, QChar('0'));
            // qDebug() << "sub_type : " << QString("%1").arg(msg->sub_type, 8, 16, QChar('0'));
            // qDebug() << "sub_type1 : " << QString("%1").arg(msg->sub_type1, 8, 16, QChar('0'));
            // qDebug() << "length : " << msg->length;
            // qDebug() << "checksum : " << QString("%1").arg(static_cast<int>(msg->checksum), 2, 16, QChar('0'));
            // qDebug() << "len : " << msg->len;
            // qDebug() << "status_flag : " << msg->status_flag;

            if(msg->status_flag != 0){
                // 提取需要写入文件的数据
                int startIndex = 4 + sizeof(upload_log_message); // 跳过帧头和结构体
                int endIndex = frame.size() - 4; // 跳过帧尾
                QByteArray dataToWrite = frame.mid(startIndex, endIndex - startIndex);

                // 验证数据长度
                if (dataToWrite.size() != static_cast<int>(msg->len)) {
                    qDebug() << "Data length mismatch. Expected: " << msg->len << ", Actual: " << dataToWrite.size();
                    continue;
                }

                QString filePath = "log.zip";
                QFile file(filePath); // 直接使用 QString 类型的路径
                if (file.open(QIODevice::Append | QIODevice::WriteOnly)) {
                    qint64 bytesWritten = file.write(dataToWrite);
                    if (bytesWritten == -1) {
                        qDebug() << "Failed to write data to log.zip.";
                    } else {
                        qDebug() << "Successfully wrote " << bytesWritten << " bytes to log.zip.";
                    }
                    file.close();
                } else {
                    qDebug() << "Failed to open log.zip for writing.";
                }

                QByteArray data1(reinterpret_cast<const char*>(LogNext), sizeof(LogNext));
                // 向客户端发送消息
                qint64 bytesWritten = socket10002->write(data1);
                if (bytesWritten == -1) {
                    qDebug() << "Failed to send Log NEXT message to client";
                } else {
                    qDebug() << "Successfully sent Log NEXT message to client, bytes written: " << bytesWritten;
                }
            } else {
                upload_end_message EndMsg;

                // 为结构体成员赋值
                EndMsg.header = 0xff5affa5;
                EndMsg.tail   = 0xffa5ff5a;
        
                EndMsg.message_type = 0x0f;
                EndMsg.sub_type = 0x03;
                EndMsg.sub_type1 = 0x00;
                EndMsg.length = 130;
                EndMsg.checksum = 0x6c;
            
                // 为字符数组赋值
                const char* str = "log.zip";
                qstrncpy(EndMsg.name, str, sizeof(EndMsg.name));
                EndMsg.name[sizeof(EndMsg.name) - 1] = '\0'; // 确保字符串以 '\0' 结尾
                EndMsg.status = 0x00;
                EndMsg.flag = 0x00;

                // 修改这里，传入 EndMsg 的地址
                QByteArray data2(reinterpret_cast<const char*>(&EndMsg), sizeof(struct upload_end_message));
                // 向客户端发送消息
                qint64 bytesWritten = socket10002->write(data2);
                if (bytesWritten == -1) {
                    qDebug() << "Failed to send Log END message to client";
                } else {
                    qDebug() << "Successfully sent Log END message to client, bytes written: " << bytesWritten;
                }
                QString message = "日志获取成功！";

                // 创建一个消息框并显示消息
                QMessageBox::information(nullptr, "消息提示", message);

                LogRequestFlag = false;// 日志完毕之后，清空标志位，确保下一次可以正确传输
            }
        }
    }
}

void LogUpload::handleConnection10001() {
    socket10001 = server10001->nextPendingConnection();
    if (socket10001) {
        // 获取客户端的 IP 地址和端口号
        QString clientIp = socket10001->peerAddress().toString();
        quint16 clientPort = socket10001->peerPort();
        // 打印客户端信息
        qDebug() << "客户端连接到端口 10001, IP: " << clientIp << "，端口: " << clientPort;

        connect(socket10001, &QTcpSocket::readyRead, this, &LogUpload::readDataPort10001);
        connect(socket10001, &QTcpSocket::disconnected, socket10001, &QTcpSocket::deleteLater);
    }
}

void LogUpload::handleConnection10002() {
    socket10002 = server10002->nextPendingConnection();
    if (socket10002) {
        // 获取客户端的 IP 地址和端口号
        QString clientIp = socket10002->peerAddress().toString();
        quint16 clientPort = socket10002->peerPort();
        // 打印客户端信息
        qDebug() << "客户端连接到端口 10002, IP: " << clientIp << "，端口: " << clientPort;

        connect(socket10002, &QTcpSocket::readyRead, this, &LogUpload::readDataPort10002);
        connect(socket10002, &QTcpSocket::disconnected, socket10002, &QTcpSocket::deleteLater);
    }
}
